package com.ffcs.crmd.tsp.task.netty;

import org.slf4j.Logger;

import com.ffcs.crmd.tsp.api.dto.netty.RemotingCommand;
import com.ffcs.crmd.tsp.api.netty.INettyConfigClient;
import com.ffcs.crmd.tsp.api.netty.INettyInvokeCallback;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.exception.TspRemotingException;
import com.ffcs.crmd.tsp.common.netty.enu.NettyExceptionType;
import com.ffcs.crmd.tsp.core.netty.client.NettyRemotingClientAbstract;
import com.ffcs.crmd.tsp.core.util.RemotingUtil;
import com.ffcs.crmd.tsp.task.log.TaskLogger;

import io.netty.channel.Channel;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.ResourceLeakDetector.Level;

/**
 * 
 * 功能说明:netty远程处理通信
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class NettyRemotingClient extends NettyRemotingClientAbstract {
    
    /**
     * 日志
     */
    private static final Logger LOG = TaskLogger.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 获取信号量超时时间
     */
    private static final int    semaphoreTimeoutMillis = 3000;
    
    /**
     * 获取响应超时时间
     */
    private static final int    reponseTimeoutMillis   = -1;
    
    
    public NettyRemotingClient(INettyConfigClient nettyConfig) {
        super(nettyConfig);
        ResourceLeakDetector.setLevel(Level.ADVANCED);
    }
    
    @Override
    public void start() {
        super.start();
        LOG.info("CLIENT-NETTY: client netty remoting start ok.");
    }
    
    @Override
    public void shutdown() {
        super.shutdown();
        LOG.info("CLIENT-NETTY: client netty remoting shutdown ok.");
    }
    
    @Override
    public RemotingCommand invokeSync(String addr, RemotingCommand request, long timeoutMillis)
        throws TspRemotingException {
        Channel channel = getAndCreateChannel(addr);
        if (channel != null && channel.isActive()) {
            return super.invokeSyncImpl(channel, request, timeoutMillis);
        } else if (channel != null) {
            closeChannel(addr, channel);
            String errorMsg = String.format("连接已失活，请稍后重试，或者检测网络以及服务端状态,", RemotingUtil.parseChannelRemote(channel));
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        } else {
            String errorMsg = String.format("无法连接到服务端，请检测网络或者是否有该服务端", addr);
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        }
    }
    
    @Override
    public void invokeAsync(String addr, RemotingCommand request) throws TspRemotingException{
        invokeAsync(addr, request, reponseTimeoutMillis, null, null);
    }
    
    @Override
    public void invokeAsync(String addr, RemotingCommand request, INettyInvokeCallback invokeCallback) throws TspRemotingException{
        invokeAsync(addr, request, reponseTimeoutMillis, invokeCallback, null);
    }
    
    @Override
    public void invokeAsync(String addr, RemotingCommand request,
        INettyInvokeCallback invokeCallback, INettyInvokeCallback sendFailCallback) throws TspRemotingException {
        invokeAsync(addr, request, reponseTimeoutMillis, invokeCallback, sendFailCallback);
    }
    
    @Override
    public void invokeAsync(String addr, RemotingCommand request, long reponseTimeoutMillis,
        INettyInvokeCallback invokeCallback, INettyInvokeCallback sendFailCallback) throws TspRemotingException {
        Channel channel = getAndCreateChannel(addr);
        if (channel != null && channel.isActive()) {
            super.invokeAsyncImpl(channel, request, semaphoreTimeoutMillis, reponseTimeoutMillis, invokeCallback, sendFailCallback);
        } else if (channel != null) {
            closeChannel(addr, channel);
            String errorMsg = String.format("连接已失活，请稍后重试，或者检测网络以及服务端状态,", RemotingUtil.parseChannelRemote(channel));
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        } else {
            String errorMsg = String.format("无法连接到服务端，请检测网络或者是否有该服务端", addr);
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        }
    }
    
    @Override
    public void invokeOneway(String addr, RemotingCommand request, INettyInvokeCallback invokeFailCallback) throws TspRemotingException {
        final Channel channel = getAndCreateChannel(addr);
        if (channel != null && channel.isActive()) {
            super.invokeOnewayImpl(channel, request, semaphoreTimeoutMillis, invokeFailCallback);
        } else if (channel != null) {
            closeChannel(addr, channel);
            String errorMsg = String.format("连接已失活，请稍后重试，或者检测网络以及服务端状态,", RemotingUtil.parseChannelRemote(channel));
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        } else {
            String errorMsg = String.format("无法连接到服务端，请检测网络或者是否有该服务端", addr);
            throw new TspRemotingException(errorMsg, NettyExceptionType.REQUEST_SEND_FAIL);
        }
    }
    
    @Override
    public Logger getLog() {
        return LOG;
    }
    
}
